<!DOCTYPE html>
<html>

<head>
  <title>dva核心知识与实战运用</title>
  <meta charset='utf-8'>
  <link href='https://cdn.maxiang.io/res-min/themes/marxico.css' rel='stylesheet'>
  <style>
    #preview-contents {
      margin-top: -20px;
      width: 900px;
    }

    #preview-contents img {
      max-width: 600px;
    }
  </style>
</head>

<body>
  <div id='preview-contents' class='note-content'>





    <h3 id="dva核心知识与实战运用">dva核心知识与实战运用</h3>

    <blockquote>
      <p>dva 首先是一个基于 redux 和 redux-saga 的数据流方案，然后为了简化开发体验，dva 还额外内置了 react-router 和 fetch，所以也可以理解为一个轻量级的应用框架!</p>

      <p><a href="https://dvajs.com/guide/" target="_blank">https://dvajs.com/guide/</a></p>

      <ul>
        <li>
          <p>易学易用，仅有 6 个 api，对 redux 用户尤其友好，配合 umi 使用后更是降低为 0 API</p>
        </li>
        <li>
          <p>elm 概念，通过 reducers, effects 和 subscriptions 组织 model</p>
        </li>
        <li>
          <p>插件机制，比如 dva-loading 可以自动处理 loading 状态，不用一遍遍地写 showLoading 和 hideLoading</p>
        </li>
        <li>
          <p>支持 HMR，基于 babel-plugin-dva-hmr 实现 components、routes 和 models 的 HMR</p>
        </li>
      </ul>
    </blockquote>



    <p><img longdesc="./1672407369145.png" alt="Alt text" title="" type="image/png"
        src=""
        class=""></p>



    <h4 id="1-如何使用dva">1. 如何使用dva？</h4>

    <p><strong>1.1 在create-react-app的基础上使用dva</strong> <br>
      在create-react-app脚手架的基础上，额外安装的内容：</p>

    <ul>
      <li>
        <p>无需手动进行antd按需导入</p>
      </li>
      <li>
        <p>无需安装：redux及redux-saga、react-redux、react-router-dom等，dva把这些东西都集成好了，安装一个dva就相当于安装了这些全部东西！！</p>

        <ul>
          <li>
            <p>react-router-dom使用的是v4版本「4.3.1」</p>
          </li>
          <li>
            <p>redux使用的是 v3.7.2「我们之前使用的都是v4.0」</p>
          </li>
          <li>
            <p>集成的配套插件版本有点低</p>
          </li>
          <li>
            <p>在React18的脚手架中使用dva会有警告错误！！</p>
          </li>
        </ul>
      </li>
      <li>
        <p>history 是控制路由模式的</p>
      </li>
      <li>
        <p>其余的按照之前讲的配置方案去配置webpack，包括：less、跨域代理、兼容、响应式布局等</p>
      </li>
    </ul>



    <pre class="prettyprint hljs-dark"><code class="language-json hljs"><div class="hljs-line">{
</div><div class="hljs-line">    <span class="hljs-attr">"dependencies"</span>: {
</div><div class="hljs-line">        <span class="hljs-attr">"antd"</span>: <span class="hljs-string">"^5.0.0"</span>,
</div><div class="hljs-line">        <span class="hljs-attr">"antd-icons"</span>: <span class="hljs-string">"^0.1.0-alpha.1"</span>,
</div><div class="hljs-line">        <span class="hljs-attr">"dva"</span>: <span class="hljs-string">"^2.4.1"</span>,
</div><div class="hljs-line">        <span class="hljs-attr">"http-proxy-middleware"</span>: <span class="hljs-string">"^2.0.6"</span>,
</div><div class="hljs-line">        <span class="hljs-attr">"less"</span>: <span class="hljs-string">"^4.1.3"</span>,
</div><div class="hljs-line">        <span class="hljs-attr">"less-loader"</span>: <span class="hljs-string">"^8.1.1"</span>,
</div><div class="hljs-line">        <span class="hljs-attr">"prop-types"</span>: <span class="hljs-string">"^15.8.1"</span>,
</div><div class="hljs-line">        <span class="hljs-attr">"styled-components"</span>: <span class="hljs-string">"^5.3.6"</span>,
</div><div class="hljs-line">        <span class="hljs-attr">"history"</span>: <span class="hljs-string">"4.10.1"</span>,
</div><div class="hljs-line">        ......
</div><div class="hljs-line">    }
</div><div class="hljs-line">}
</div></code></pre>

    <p>项目的结构目录，可以依然沿用之前的命名风格：</p>

    <ul>
      <li>
        <p>api 接口管理和请求封装</p>
      </li>
      <li>
        <p>assets 静态资源文件</p>
      </li>
      <li>
        <p>router 路由统一配置</p>
      </li>
      <li>
        <p>store redux公共状态管理</p>
      </li>
      <li>
        <p>views 普通业务组件</p>
      </li>
      <li>
        <p>components 公共业务组件</p>
      </li>
      <li>
        <p>index.jsx 入口</p>
      </li>
      <li>
        <p>setupProxy.js 跨域代理</p>
      </li>
      <li>
        <p>…</p>
      </li>
    </ul>

    <p>但是有很多文件的编写方式和之前是不一样的！！ <br>
      <code>index.js</code>
    </p>



    <pre class="prettyprint hljs-dark"><code class="language-javascript hljs"><div class="hljs-line"><span class="hljs-keyword">import</span> dva <span class="hljs-keyword">from</span> <span class="hljs-string">'dva'</span>;
</div><div class="hljs-line"><span class="hljs-keyword">import</span> createHistory <span class="hljs-keyword">from</span> <span class="hljs-string">'history/createHashHistory'</span>;
</div><div class="hljs-line"><span class="hljs-keyword">import</span> RouterConfig <span class="hljs-keyword">from</span> <span class="hljs-string">'./router'</span>;
</div><div class="hljs-line"><span class="hljs-keyword">import</span> voteModel <span class="hljs-keyword">from</span> <span class="hljs-string">'./store/voteModel'</span>;
</div><div class="hljs-line"><wbr>
</div><div class="hljs-line"><span class="hljs-comment">// 初始化配置</span>
</div><div class="hljs-line"><span class="hljs-keyword">const</span> app = dva({
</div><div class="hljs-line">  <span class="hljs-comment">// 设置路由模式{默认HASH路由}</span>
</div><div class="hljs-line">  history: createHistory()
</div><div class="hljs-line">});
</div><div class="hljs-line"><span class="hljs-comment">// 使用插件</span>
</div><div class="hljs-line">app.use({});
</div><div class="hljs-line"><span class="hljs-comment">// redux公共状态管理</span>
</div><div class="hljs-line">app.model(voteModel);
</div><div class="hljs-line"><span class="hljs-comment">// 路由配置</span>
</div><div class="hljs-line">app.router(RouterConfig);
</div><div class="hljs-line"><span class="hljs-comment">// 启动dva</span>
</div><div class="hljs-line">app.start(<span class="hljs-string">'#root'</span>);
</div></code></pre>

    <p><code>router/index.js</code> 配置页面入口和路由</p>



    <pre class="prettyprint hljs-dark"><code class="language-javascript hljs"><div class="hljs-line"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
</div><div class="hljs-line"><span class="hljs-keyword">import</span> { Router, Route, Switch, Redirect } <span class="hljs-keyword">from</span> <span class="hljs-string">'dva/router'</span>;
</div><div class="hljs-line"><span class="hljs-keyword">import</span> Vote <span class="hljs-keyword">from</span> <span class="hljs-string">'../views/Vote'</span>;
</div><div class="hljs-line"><span class="hljs-keyword">import</span> Demo <span class="hljs-keyword">from</span> <span class="hljs-string">'../views/Demo'</span>;
</div><div class="hljs-line"><span class="hljs-comment">/* ANTD */</span>
</div><div class="hljs-line"><span class="hljs-keyword">import</span> { ConfigProvider } <span class="hljs-keyword">from</span> <span class="hljs-string">'antd'</span>;
</div><div class="hljs-line"><span class="hljs-keyword">import</span> zhCN <span class="hljs-keyword">from</span> <span class="hljs-string">'antd/locale/zh_CN'</span>;
</div><div class="hljs-line"><span class="hljs-keyword">import</span> <span class="hljs-string">'../assets/reset.min.css'</span>;
</div><div class="hljs-line"><wbr>
</div><div class="hljs-line"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">RouterConfig</span>(<span class="hljs-params">{ history }</span>) </span>{
</div><div class="hljs-line">    <span class="hljs-keyword">return</span> (
</div><div class="hljs-line">        &lt;ConfigProvider locale={zhCN}&gt;
</div><div class="hljs-line">            &lt;Router history={history}&gt;
</div><div class="hljs-line">                &lt;Switch&gt;
</div><div class="hljs-line">                    &lt;Route path="/" exact component={Vote} /&gt;
</div><div class="hljs-line">                    &lt;Route path="/demo" component={Demo} /&gt;
</div><div class="hljs-line">                    &lt;Redirect to="/" /&gt;
</div><div class="hljs-line">                &lt;/Switch&gt;
</div><div class="hljs-line">            &lt;/Router&gt;
</div><div class="hljs-line">        &lt;/ConfigProvider&gt;
</div><div class="hljs-line">    );
</div><div class="hljs-line">}
</div><div class="hljs-line">export default RouterConfig;
</div></code></pre>

    <p><code>store/voteModel.js</code> 配置每个模块的Model，包含：状态、reducer、异步派发的方法等</p>



    <pre class="prettyprint hljs-dark"><code class="language-javascript hljs"><div class="hljs-line"><span class="hljs-keyword">import</span> _ <span class="hljs-keyword">from</span> <span class="hljs-string">'../assets/utils'</span>;
</div><div class="hljs-line"><span class="hljs-keyword">const</span> delay = <span class="hljs-function">(<span class="hljs-params">interval = <span class="hljs-number">1000</span></span>) =&gt;</span> {
</div><div class="hljs-line">    <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function"><span class="hljs-params">resolve</span> =&gt;</span> {
</div><div class="hljs-line">        setTimeout(<span class="hljs-function"><span class="hljs-params">()</span> =&gt;</span> {
</div><div class="hljs-line">            resolve();
</div><div class="hljs-line">        }, interval);
</div><div class="hljs-line">    });
</div><div class="hljs-line">};
</div><div class="hljs-line"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> {
</div><div class="hljs-line">    <span class="hljs-attr">namespace</span>: <span class="hljs-string">'vote'</span>,
</div><div class="hljs-line">    <span class="hljs-attr">state</span>: {
</div><div class="hljs-line">        <span class="hljs-attr">supNum</span>: <span class="hljs-number">10</span>,
</div><div class="hljs-line">        <span class="hljs-attr">oppNum</span>: <span class="hljs-number">5</span>
</div><div class="hljs-line">    },
</div><div class="hljs-line">    <span class="hljs-attr">reducers</span>: {
</div><div class="hljs-line">        support(state, action) {
</div><div class="hljs-line">            state = _.clone(<span class="hljs-literal">true</span>, state);
</div><div class="hljs-line">            <span class="hljs-keyword">let</span> { payload = <span class="hljs-number">1</span> } = action;
</div><div class="hljs-line">            state.supNum += payload;
</div><div class="hljs-line">            <span class="hljs-keyword">return</span> state;
</div><div class="hljs-line">        },
</div><div class="hljs-line">        oppose(state, action) {
</div><div class="hljs-line">            state = _.clone(<span class="hljs-literal">true</span>, state);
</div><div class="hljs-line">            <span class="hljs-keyword">let</span> { payload = <span class="hljs-number">1</span> } = action;
</div><div class="hljs-line">            state.oppNum += payload;
</div><div class="hljs-line">            <span class="hljs-keyword">return</span> state;
</div><div class="hljs-line">        }
</div><div class="hljs-line">    },
</div><div class="hljs-line">    <span class="hljs-attr">effects</span>: {
</div><div class="hljs-line">        <span class="hljs-attr">supportAsync</span>: [
</div><div class="hljs-line">            <span class="hljs-function"><span class="hljs-keyword">function</span>* (<span class="hljs-params">{ payload }, { call, put }</span>) </span>{
</div><div class="hljs-line">                <span class="hljs-keyword">yield</span> call(delay, <span class="hljs-number">2000</span>);
</div><div class="hljs-line">                <span class="hljs-keyword">yield</span> put({
</div><div class="hljs-line">                    <span class="hljs-attr">type</span>: <span class="hljs-string">'support'</span>,
</div><div class="hljs-line">                    payload
</div><div class="hljs-line">                });
</div><div class="hljs-line">            },
</div><div class="hljs-line">            { <span class="hljs-attr">type</span>: <span class="hljs-string">'takeLatest'</span> }
</div><div class="hljs-line">        ],
</div><div class="hljs-line">        *opposeAsync({ payload }, { call, put }) {
</div><div class="hljs-line">            <span class="hljs-keyword">yield</span> call(delay, <span class="hljs-number">2000</span>);
</div><div class="hljs-line">            <span class="hljs-keyword">yield</span> put({
</div><div class="hljs-line">                <span class="hljs-attr">type</span>: <span class="hljs-string">'oppose'</span>,
</div><div class="hljs-line">                payload
</div><div class="hljs-line">            });
</div><div class="hljs-line">        }
</div><div class="hljs-line">    }
</div><div class="hljs-line">};
</div></code></pre>

    <p>在组件中如何使用呢？</p>



    <pre class="prettyprint hljs-dark"><code class="language-javascript hljs"><div class="hljs-line"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
</div><div class="hljs-line"><span class="hljs-keyword">import</span> styled <span class="hljs-keyword">from</span> <span class="hljs-string">"styled-components"</span>;
</div><div class="hljs-line"><span class="hljs-keyword">import</span> { Button } <span class="hljs-keyword">from</span> <span class="hljs-string">'antd'</span>;
</div><div class="hljs-line"><span class="hljs-keyword">import</span> { connect } <span class="hljs-keyword">from</span> <span class="hljs-string">'dva'</span>;
</div><div class="hljs-line"><wbr>
</div><div class="hljs-line"><span class="hljs-comment">// 样式处理</span>
</div><div class="hljs-line"><span class="hljs-keyword">const</span> VoteBox = styled.div<span class="hljs-string">`</span>
</div><div class="hljs-line"><span class="hljs-string">    ...</span>
</div><div class="hljs-line"><span class="hljs-string">`</span>;
</div><div class="hljs-line"><wbr>
</div><div class="hljs-line"><span class="hljs-keyword">const</span> Vote = <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Vote</span>(<span class="hljs-params">props</span>) </span>{
</div><div class="hljs-line">    <span class="hljs-keyword">let</span> { supNum, oppNum, dispatch } = props;
</div><div class="hljs-line">    <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">VoteBox</span>&gt;</span></span>
</div><div class="hljs-line"><span class="xml">        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"header"</span>&gt;</span></span>
</div><div class="hljs-line"><span class="xml">            <span class="hljs-tag">&lt;<span class="hljs-name">h2</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"title"</span>&gt;</span>React是很棒的前端框架<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span></span>
</div><div class="hljs-line"><span class="xml">            <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"num"</span>&gt;</span>{supNum + oppNum}<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span></span>
</div><div class="hljs-line"><span class="xml">        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
</div><div class="hljs-line"><span class="xml">        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"main"</span>&gt;</span></span>
</div><div class="hljs-line"><span class="xml">            <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>支持人数：{supNum}人<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></span>
</div><div class="hljs-line"><span class="xml">            <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>反对人数：{oppNum}人<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></span>
</div><div class="hljs-line"><span class="xml">        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
</div><div class="hljs-line"><span class="xml">        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"footer"</span>&gt;</span></span>
</div><div class="hljs-line"><span class="xml">            <span class="hljs-tag">&lt;<span class="hljs-name">Button</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"primary"</span></span></span>
</div><div class="hljs-line"><span class="xml">                <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt; {</span>
</div><div class="hljs-line"><span class="xml">                    dispatch({</span>
</div><div class="hljs-line"><span class="xml">                        type: 'vote/supportAsync',</span>
</div><div class="hljs-line"><span class="xml">                        payload: 10</span>
</div><div class="hljs-line"><span class="xml">                    });</span>
</div><div class="hljs-line"><span class="xml">                }}&gt;</span>
</div><div class="hljs-line"><span class="xml">                支持</span>
</div><div class="hljs-line"><span class="xml">            <span class="hljs-tag">&lt;/<span class="hljs-name">Button</span>&gt;</span></span>
</div><div class="hljs-line"><span class="xml">            <span class="hljs-tag">&lt;<span class="hljs-name">Button</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"primary"</span> <span class="hljs-attr">danger</span></span></span>
</div><div class="hljs-line"><span class="xml">                <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt; {</span>
</div><div class="hljs-line"><span class="xml">                    dispatch({</span>
</div><div class="hljs-line"><span class="xml">                        type: 'vote/opposeAsync'</span>
</div><div class="hljs-line"><span class="xml">                    });</span>
</div><div class="hljs-line"><span class="xml">                }}&gt;</span>
</div><div class="hljs-line"><span class="xml">                反对</span>
</div><div class="hljs-line"><span class="xml">            <span class="hljs-tag">&lt;/<span class="hljs-name">Button</span>&gt;</span></span>
</div><div class="hljs-line"><span class="xml">        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
</div><div class="hljs-line"><span class="xml">    <span class="hljs-tag">&lt;/<span class="hljs-name">VoteBox</span>&gt;</span></span>;
</div><div class="hljs-line">};
</div><div class="hljs-line"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> connect(<span class="hljs-function"><span class="hljs-params">state</span> =&gt;</span> state.vote)(Vote);
</div></code></pre>

    <p><strong>1.2 但是更多的时候，我们会直接使用 dva 自带的脚手架创建项目</strong></p>

    <blockquote>
      <p>dva脚手架创建的项目是基于<code>roadhog /rəʊd hog/</code>进行webpack的配置！！ <br>
        roadhog是一个cli工具，提供server、 build和test三个命令，分别用于本地调试和构建，并且提供了特别易用的mock功能。命令行体验和create-react-app一致，配置略有不同，比如默认开启 css
        modules，然后还提供了JSON格式的配置方式！ <br>
        <span>$</span> npm install dva-cli -g <br>
        <span>$</span> dva -v <br>
        <span>$</span> dva new my-project
      </p>
    </blockquote>



    <p><img longdesc="./1672411473222.png" alt="Alt text" title="" type="image/png"
        src=""
        class=""></p>

    <p><code>package.json</code></p>



    <pre class="prettyprint hljs-dark"><code class="hljs lasso"><div class="hljs-line">{
</div><div class="hljs-line">  <span class="hljs-string">"private"</span>: <span class="hljs-literal">true</span>,
</div><div class="hljs-line">  <span class="hljs-string">"scripts"</span>: {
</div><div class="hljs-line">    <span class="hljs-string">"start"</span>: <span class="hljs-string">"cross-env PORT=3000 HOST=127.0.0.1 roadhog server"</span>, <span class="hljs-comment">//开发环境启动</span>
</div><div class="hljs-line">    <span class="hljs-string">"build"</span>: <span class="hljs-string">"roadhog build"</span>, <span class="hljs-comment">//生产环境打包</span>
</div><div class="hljs-line">    <span class="hljs-string">"lint"</span>: <span class="hljs-string">"eslint --ext .js src test"</span>, <span class="hljs-comment">//单元测试</span>
</div><div class="hljs-line">    <span class="hljs-string">"precommit"</span>: <span class="hljs-string">"npm run lint"</span>
</div><div class="hljs-line">  },
</div><div class="hljs-line">  <span class="hljs-string">"dependencies"</span>: {
</div><div class="hljs-line">    <span class="hljs-string">"@babel/polyfill"</span>: <span class="hljs-string">"^7.12.1"</span>,
</div><div class="hljs-line">    <span class="hljs-string">"antd"</span>: <span class="hljs-string">"4.24.7"</span>, <span class="hljs-comment">//注意版本用v4「不是最新的v5」</span>
</div><div class="hljs-line">    <span class="hljs-string">"antd-icons"</span>: <span class="hljs-string">"^0.1.0-alpha.1"</span>,
</div><div class="hljs-line">    <span class="hljs-string">"babel-plugin-import"</span>: <span class="hljs-string">"^1.13.5"</span>, <span class="hljs-comment">//antd按需导入</span>
</div><div class="hljs-line">    <span class="hljs-string">"dva"</span>: <span class="hljs-string">"^2.4.1"</span>,
</div><div class="hljs-line">    <span class="hljs-string">"history"</span>: <span class="hljs-string">"4.10.1"</span>, <span class="hljs-comment">//管理路由模式的「用v4不是最新的v5版本」</span>
</div><div class="hljs-line">    <span class="hljs-string">"lib-flexible"</span>: <span class="hljs-string">"^0.3.2"</span>,
</div><div class="hljs-line">    <span class="hljs-string">"postcss-pxtorem"</span>: <span class="hljs-string">"5.1.1"</span>,
</div><div class="hljs-line">    <span class="hljs-string">"prop-types"</span>: <span class="hljs-string">"^15.8.1"</span>,
</div><div class="hljs-line">    <span class="hljs-string">"qs"</span>: <span class="hljs-string">"^6.11.0"</span>,
</div><div class="hljs-line">    <span class="hljs-string">"react"</span>: <span class="hljs-string">"^16.2.0"</span>, <span class="hljs-comment">//react使用的是v16版本</span>
</div><div class="hljs-line">    <span class="hljs-string">"react-dom"</span>: <span class="hljs-string">"^16.2.0"</span>,
</div><div class="hljs-line">    <span class="hljs-string">"styled-components"</span>: <span class="hljs-string">"^5.3.6"</span>
</div><div class="hljs-line">  },
</div><div class="hljs-line">  <span class="hljs-string">"devDependencies"</span>: {
</div><div class="hljs-line">    <span class="hljs-string">"babel-plugin-dva-hmr"</span>: <span class="hljs-string">"^0.3.2"</span>, <span class="hljs-comment">//热更新</span>
</div><div class="hljs-line">    <span class="hljs-string">"cross-env"</span>: <span class="hljs-string">"^7.0.3"</span>,
</div><div class="hljs-line">    <span class="hljs-string">"less"</span>: <span class="hljs-string">"4.1.3"</span>,
</div><div class="hljs-line">    <span class="hljs-string">"less-loader"</span>: <span class="hljs-string">"8.1.1"</span>,
</div><div class="hljs-line">    <span class="hljs-params">...</span>
</div><div class="hljs-line">  }
</div><div class="hljs-line">}
</div></code></pre>

    <p><strong><code>修改webpack配置项</code></strong></p>

    <p>修改启动的域名和端口号：设置环境变量即可</p>

    <ul>
      <li>
        <p>PORT</p>
      </li>
      <li>
        <p>HOST</p>
      </li>
      <li>
        <p>HTTPS 是否开启https,默认关闭</p>
      </li>
      <li>
        <p>BROWSER 设为none时不自动打开浏览器</p>
      </li>
      <li>
        <p>CLEAR_CONSOLE 设为none时清屏</p>
      </li>
    </ul>

    <blockquote>
      <p>“start”: “cross-env PORT=3000 HOST=127.0.0.1 roadhog server”,</p>
    </blockquote>

    <p>把<code>.webpackrc</code>改为<code>.webpackrc.js</code>，这样就可以按照JS方式去编写配置项了！！</p>

    <ul>
      <li>
        <p>修改入口、出口、打包配置等</p>
      </li>
      <li>
        <p>Antd按需导入</p>
      </li>
      <li>
        <p>配置跨域代理</p>
      </li>
      <li>
        <p>配置响应式布局方案</p>
      </li>
      <li>
        <p>配置less</p>
      </li>
      <li>
        <p>不同环境下的配置</p>
      </li>
      <li>
        <p>浏览器兼容</p>
      </li>
      <li>
        <p>……</p>
      </li>
    </ul>



    <pre class="prettyprint hljs-dark"><code class="language-javascript hljs"><div class="hljs-line"><span class="hljs-keyword">import</span> px2rem <span class="hljs-keyword">from</span> <span class="hljs-string">'postcss-pxtorem'</span>;
</div><div class="hljs-line"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> {
</div><div class="hljs-line">    <span class="hljs-comment">/* 基础配置 */</span>
</div><div class="hljs-line">    <span class="hljs-string">"entry"</span>: <span class="hljs-string">"src/index.js"</span>, <span class="hljs-comment">//配置多入口：src/enter/*.js</span>
</div><div class="hljs-line">    <span class="hljs-string">"outputPath"</span>: <span class="hljs-string">"./dist"</span>,
</div><div class="hljs-line">    <span class="hljs-string">"publicPath"</span>: <span class="hljs-string">"/"</span>,
</div><div class="hljs-line">    <span class="hljs-string">"hash"</span>: <span class="hljs-literal">true</span>,
</div><div class="hljs-line">    <span class="hljs-string">"html"</span>: {
</div><div class="hljs-line">        <span class="hljs-string">"template"</span>: <span class="hljs-string">"./public/index.ejs"</span>
</div><div class="hljs-line">    },
</div><div class="hljs-line">    <span class="hljs-comment">/* 配置LESS */</span>
</div><div class="hljs-line">    <span class="hljs-string">"disableCSSModules"</span>: <span class="hljs-literal">true</span>,
</div><div class="hljs-line">    <span class="hljs-comment">/* 配置PX转REM */</span>
</div><div class="hljs-line">    <span class="hljs-string">"extraPostCSSPlugins"</span>: [
</div><div class="hljs-line">        px2rem({
</div><div class="hljs-line">            <span class="hljs-string">"rootValue"</span>: <span class="hljs-number">75</span>,
</div><div class="hljs-line">            <span class="hljs-string">"propList"</span>: [<span class="hljs-string">'*'</span>]
</div><div class="hljs-line">        })
</div><div class="hljs-line">    ],
</div><div class="hljs-line">    <span class="hljs-comment">/* 配置BABEL的插件 */</span>
</div><div class="hljs-line">    <span class="hljs-string">"extraBabelPlugins"</span>: [
</div><div class="hljs-line">        <span class="hljs-comment">// antd按需导入</span>
</div><div class="hljs-line">        [
</div><div class="hljs-line">            <span class="hljs-string">"import"</span>,
</div><div class="hljs-line">            {
</div><div class="hljs-line">                <span class="hljs-string">"libraryName"</span>: <span class="hljs-string">"antd"</span>,
</div><div class="hljs-line">                <span class="hljs-string">"libraryDirectory"</span>: <span class="hljs-string">"es"</span>,
</div><div class="hljs-line">                <span class="hljs-string">"style"</span>: <span class="hljs-string">"css"</span>
</div><div class="hljs-line">            }
</div><div class="hljs-line">        ],
</div><div class="hljs-line">        <span class="hljs-comment">// 配置PX转REM</span>
</div><div class="hljs-line">        [
</div><div class="hljs-line">            <span class="hljs-string">"styled-components-px2rem"</span>,
</div><div class="hljs-line">            {
</div><div class="hljs-line">                <span class="hljs-string">"rootValue"</span>: <span class="hljs-number">75</span>
</div><div class="hljs-line">            }
</div><div class="hljs-line">        ]
</div><div class="hljs-line">    ],
</div><div class="hljs-line">    <span class="hljs-comment">/* 配置跨域代理 */</span>
</div><div class="hljs-line">    <span class="hljs-string">"proxy"</span>: {
</div><div class="hljs-line">        <span class="hljs-string">"/api"</span>: {
</div><div class="hljs-line">            <span class="hljs-string">"target"</span>: <span class="hljs-string">"https://news-at.zhihu.com/api/4"</span>,
</div><div class="hljs-line">            <span class="hljs-string">"changeOrigin"</span>: <span class="hljs-literal">true</span>,
</div><div class="hljs-line">            <span class="hljs-string">"ws"</span>: <span class="hljs-literal">true</span>,
</div><div class="hljs-line">            <span class="hljs-string">"pathRewrite"</span>: {
</div><div class="hljs-line">                <span class="hljs-string">"/api"</span>: <span class="hljs-string">""</span>
</div><div class="hljs-line">            }
</div><div class="hljs-line">        }
</div><div class="hljs-line">    },
</div><div class="hljs-line">    <span class="hljs-comment">/* 不同环境下的不同配置 */</span>
</div><div class="hljs-line">    <span class="hljs-string">"env"</span>: {
</div><div class="hljs-line">        <span class="hljs-string">"development"</span>: {
</div><div class="hljs-line">            <span class="hljs-string">"extraBabelPlugins"</span>: [
</div><div class="hljs-line">                <span class="hljs-string">"dva-hmr"</span>
</div><div class="hljs-line">            ]
</div><div class="hljs-line">        }
</div><div class="hljs-line">    }
</div><div class="hljs-line">};
</div></code></pre>

    <p>浏览器兼容：默认情况下，ES6语法和CSS3的兼容已经处理，如果想处理ES6内置API的兼容，则导入@babel/polyfill即可「入口导入」！！</p>

    <hr>



    <h4 id="2-dva中的路由配置">2. dva中的路由配置</h4>

    <p><code>index.js</code></p>



    <pre class="prettyprint hljs-dark"><code class="language-javascript hljs"><div class="hljs-line"><span class="hljs-keyword">import</span> dva <span class="hljs-keyword">from</span> <span class="hljs-string">'dva'</span>;
</div><div class="hljs-line"><span class="hljs-comment">/*</span>
</div><div class="hljs-line"><span class="hljs-comment"> 安装history模块「安装v4.10.1版本，不建议安装最新版本」</span>
</div><div class="hljs-line"><span class="hljs-comment"> $ yarn add history@4.10.1</span>
</div><div class="hljs-line"><span class="hljs-comment"> 默认开启的就是HASH路由，如果想使用History路由，则导入createBrowserHistory!!</span>
</div><div class="hljs-line"><span class="hljs-comment">*/</span>
</div><div class="hljs-line"><span class="hljs-keyword">import</span> createHistory <span class="hljs-keyword">from</span> <span class="hljs-string">'history/createHashHistory'</span>;
</div><div class="hljs-line"><span class="hljs-keyword">const</span> app = dva({
</div><div class="hljs-line">    <span class="hljs-comment">// 指定路由模式</span>
</div><div class="hljs-line">    history: createHistory()
</div><div class="hljs-line">});
</div><div class="hljs-line">...
</div><div class="hljs-line">app.router(<span class="hljs-built_in">require</span>(<span class="hljs-string">'./router'</span>).default);
</div><div class="hljs-line">app.start(<span class="hljs-string">'#root'</span>);
</div></code></pre>

    <p><code>router.js</code></p>



    <pre class="prettyprint hljs-dark"><code class="language-javascript hljs"><div class="hljs-line"><span class="hljs-comment">/* </span>
</div><div class="hljs-line"><span class="hljs-comment">dva/router中包含了react-router-dom v5版本中所有API，以及react-router-redux中的的API </span>
</div><div class="hljs-line"><span class="hljs-comment">*/</span>
</div><div class="hljs-line"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
</div><div class="hljs-line"><span class="hljs-keyword">import</span> { Router, Route, Switch, Redirect } <span class="hljs-keyword">from</span> <span class="hljs-string">'dva/router'</span>;
</div><div class="hljs-line"><span class="hljs-keyword">import</span> Vote <span class="hljs-keyword">from</span> <span class="hljs-string">'./routes/Vote'</span>;
</div><div class="hljs-line"><span class="hljs-keyword">import</span> Demo <span class="hljs-keyword">from</span> <span class="hljs-string">'./routes/Demo'</span>;
</div><div class="hljs-line"><span class="hljs-keyword">import</span> Personal <span class="hljs-keyword">from</span> <span class="hljs-string">'./routes/Personal'</span>;
</div><div class="hljs-line"><wbr>
</div><div class="hljs-line"><span class="hljs-comment">/* ANTD */</span>
</div><div class="hljs-line">...
</div><div class="hljs-line"><wbr>
</div><div class="hljs-line">const RouterConfig = <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">RouterConfig</span>(<span class="hljs-params">{ history }</span>) </span>{
</div><div class="hljs-line">  <span class="hljs-keyword">return</span> &lt;ConfigProvider locale={zhCN}&gt;
</div><div class="hljs-line">    &lt;Router history={history}&gt;
</div><div class="hljs-line">      &lt;Switch&gt;
</div><div class="hljs-line">        &lt;Route path="/" exact component={Vote} /&gt;
</div><div class="hljs-line">        &lt;Route path="/demo" component={Demo} /&gt;
</div><div class="hljs-line">        &lt;Route path="/personal" component={Personal} /&gt;
</div><div class="hljs-line">        &lt;Redirect to="/" /&gt;
</div><div class="hljs-line">      &lt;/Switch&gt;
</div><div class="hljs-line">    &lt;/Router&gt;
</div><div class="hljs-line">  &lt;/ConfigProvider&gt;;
</div><div class="hljs-line">}
</div><div class="hljs-line">export default RouterConfig;
</div></code></pre>

    <p><code>路由懒加载</code></p>



    <pre class="prettyprint hljs-dark"><code class="language-javascript hljs"><div class="hljs-line"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
</div><div class="hljs-line"><span class="hljs-keyword">import</span> { Router, Route, Switch, Redirect } <span class="hljs-keyword">from</span> <span class="hljs-string">'dva/router'</span>;
</div><div class="hljs-line"><span class="hljs-keyword">import</span> Vote <span class="hljs-keyword">from</span> <span class="hljs-string">'./routes/Vote'</span>;
</div><div class="hljs-line"><span class="hljs-keyword">import</span> dynamic <span class="hljs-keyword">from</span> <span class="hljs-string">'dva/dynamic'</span>; <span class="hljs-comment">//实现动态组件的API</span>
</div><div class="hljs-line"><wbr>
</div><div class="hljs-line"><span class="hljs-comment">/* ANTD */</span>
</div><div class="hljs-line">...
</div><div class="hljs-line"><wbr>
</div><div class="hljs-line">const RouterConfig = <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">RouterConfig</span>(<span class="hljs-params">{ history, app }</span>) </span>{
</div><div class="hljs-line">  <span class="hljs-comment">/* 异步组件 */</span>
</div><div class="hljs-line">  <span class="hljs-keyword">const</span> DemoAsync = dynamic({
</div><div class="hljs-line">    app,
</div><div class="hljs-line">    <span class="hljs-attr">models</span>: <span class="hljs-function"><span class="hljs-params">()</span> =&gt;</span> [
</div><div class="hljs-line">      <span class="hljs-keyword">import</span>(<span class="hljs-comment">/* webpackChunkName:"demo" */</span> <span class="hljs-string">'./models/demoModel'</span>)
</div><div class="hljs-line">    ],
</div><div class="hljs-line">    <span class="hljs-attr">component</span>: <span class="hljs-function"><span class="hljs-params">()</span> =&gt;</span> <span class="hljs-keyword">import</span>(<span class="hljs-comment">/* webpackChunkName:"demo" */</span> <span class="hljs-string">'./routes/Demo'</span>)
</div><div class="hljs-line">  });
</div><div class="hljs-line">  <span class="hljs-keyword">const</span> PersonalAsync = dynamic({
</div><div class="hljs-line">    app,
</div><div class="hljs-line">    <span class="hljs-attr">models</span>: <span class="hljs-function"><span class="hljs-params">()</span> =&gt;</span> [
</div><div class="hljs-line">      <span class="hljs-keyword">import</span>(<span class="hljs-comment">/* webpackChunkName:"personal" */</span> <span class="hljs-string">'./models/personalModel'</span>)
</div><div class="hljs-line">    ],
</div><div class="hljs-line">    <span class="hljs-attr">component</span>: <span class="hljs-function"><span class="hljs-params">()</span> =&gt;</span> <span class="hljs-keyword">import</span>(<span class="hljs-comment">/* webpackChunkName:"personal" */</span> <span class="hljs-string">'./routes/Personal'</span>)
</div><div class="hljs-line">  });
</div><div class="hljs-line"><wbr>
</div><div class="hljs-line">  <span class="hljs-keyword">return</span> &lt;ConfigProvider locale={zhCN}&gt;
</div><div class="hljs-line">    &lt;Router history={history}&gt;
</div><div class="hljs-line">      &lt;Switch&gt;
</div><div class="hljs-line">        &lt;Route path="/" exact component={Vote} /&gt;
</div><div class="hljs-line">        &lt;Route path="/demo" component={DemoAsync} /&gt;
</div><div class="hljs-line">        &lt;Route path="/personal" component={PersonalAsync} /&gt;
</div><div class="hljs-line">        &lt;Redirect to="/" /&gt;
</div><div class="hljs-line">      &lt;/Switch&gt;
</div><div class="hljs-line">    &lt;/Router&gt;
</div><div class="hljs-line">  &lt;/ConfigProvider&gt;;
</div><div class="hljs-line">}
</div><div class="hljs-line">export default RouterConfig;
</div></code></pre>

    <p><code>配置路由表和二级路由</code> <br>
      routerRoutes.js 路由表</p>



    <pre class="prettyprint hljs-dark"><code class="language-javascript hljs"><div class="hljs-line"><span class="hljs-keyword">import</span> Vote <span class="hljs-keyword">from</span> <span class="hljs-string">'./routes/Vote'</span>;
</div><div class="hljs-line"><span class="hljs-keyword">import</span> dynamic <span class="hljs-keyword">from</span> <span class="hljs-string">'dva/dynamic'</span>;
</div><div class="hljs-line"><span class="hljs-comment">/* 配置路由懒加载 */</span>
</div><div class="hljs-line"><span class="hljs-keyword">const</span> lazy = <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">lazy</span>(<span class="hljs-params">models, component</span>) </span>{
</div><div class="hljs-line">    <span class="hljs-keyword">return</span> dynamic({
</div><div class="hljs-line">        <span class="hljs-attr">app</span>: <span class="hljs-built_in">window</span>.app, <span class="hljs-comment">//在入口处挂载到window上</span>
</div><div class="hljs-line">        models,
</div><div class="hljs-line">        component
</div><div class="hljs-line">    });
</div><div class="hljs-line">};
</div><div class="hljs-line"><wbr>
</div><div class="hljs-line"><span class="hljs-keyword">const</span> routes = [{
</div><div class="hljs-line">    <span class="hljs-attr">path</span>: <span class="hljs-string">'/'</span>,
</div><div class="hljs-line">    <span class="hljs-attr">exact</span>: <span class="hljs-literal">true</span>,
</div><div class="hljs-line">    <span class="hljs-attr">component</span>: Vote,
</div><div class="hljs-line">    <span class="hljs-attr">meta</span>: { <span class="hljs-attr">title</span>: <span class="hljs-string">'首页'</span> }
</div><div class="hljs-line">}, {
</div><div class="hljs-line">    <span class="hljs-attr">path</span>: <span class="hljs-string">'/demo'</span>,
</div><div class="hljs-line">    <span class="hljs-attr">component</span>: lazy(
</div><div class="hljs-line">        <span class="hljs-function"><span class="hljs-params">()</span> =&gt;</span> [<span class="hljs-keyword">import</span>(<span class="hljs-comment">/* webpackChunkName:"demo" */</span> <span class="hljs-string">'./models/demoModel'</span>)],
</div><div class="hljs-line">        () =&gt; <span class="hljs-keyword">import</span>(<span class="hljs-comment">/* webpackChunkName:"demo" */</span> <span class="hljs-string">'./routes/Demo'</span>)
</div><div class="hljs-line">    ),
</div><div class="hljs-line">    <span class="hljs-attr">meta</span>: { <span class="hljs-attr">title</span>: <span class="hljs-string">'测试页'</span> }
</div><div class="hljs-line">}, {
</div><div class="hljs-line">    <span class="hljs-attr">path</span>: <span class="hljs-string">'/personal'</span>,
</div><div class="hljs-line">    <span class="hljs-attr">component</span>: lazy(
</div><div class="hljs-line">        <span class="hljs-function"><span class="hljs-params">()</span> =&gt;</span> [<span class="hljs-keyword">import</span>(<span class="hljs-comment">/* webpackChunkName:"personal" */</span> <span class="hljs-string">'./models/personalModel'</span>)],
</div><div class="hljs-line">        () =&gt; <span class="hljs-keyword">import</span>(<span class="hljs-comment">/* webpackChunkName:"personal" */</span> <span class="hljs-string">'./routes/Personal'</span>)
</div><div class="hljs-line">    ),
</div><div class="hljs-line">    <span class="hljs-attr">meta</span>: { <span class="hljs-attr">title</span>: <span class="hljs-string">'个人中心'</span> },
</div><div class="hljs-line">    <span class="hljs-comment">/* 二级路由 */</span>
</div><div class="hljs-line">    children: [{
</div><div class="hljs-line">        <span class="hljs-attr">redirect</span>: <span class="hljs-literal">true</span>,
</div><div class="hljs-line">        <span class="hljs-attr">exact</span>: <span class="hljs-literal">true</span>,
</div><div class="hljs-line">        <span class="hljs-attr">from</span>: <span class="hljs-string">'/personal'</span>,
</div><div class="hljs-line">        <span class="hljs-attr">to</span>: <span class="hljs-string">'/personal/order'</span>
</div><div class="hljs-line">    }, {
</div><div class="hljs-line">        <span class="hljs-attr">path</span>: <span class="hljs-string">'/personal/order'</span>,
</div><div class="hljs-line">        <span class="hljs-attr">component</span>: lazy(
</div><div class="hljs-line">            <span class="hljs-function"><span class="hljs-params">()</span> =&gt;</span> [],
</div><div class="hljs-line">            () =&gt; <span class="hljs-keyword">import</span>(<span class="hljs-comment">/* webpackChunkName:"personal" */</span> <span class="hljs-string">'./routes/personal/MyOrder'</span>)
</div><div class="hljs-line">        ),
</div><div class="hljs-line">        <span class="hljs-attr">meta</span>: { <span class="hljs-attr">title</span>: <span class="hljs-string">'个人中心-我的订单'</span> }
</div><div class="hljs-line">    }, {
</div><div class="hljs-line">        <span class="hljs-attr">path</span>: <span class="hljs-string">'/personal/profile'</span>,
</div><div class="hljs-line">        <span class="hljs-attr">component</span>: lazy(
</div><div class="hljs-line">            <span class="hljs-function"><span class="hljs-params">()</span> =&gt;</span> [],
</div><div class="hljs-line">            () =&gt; <span class="hljs-keyword">import</span>(<span class="hljs-comment">/* webpackChunkName:"personal" */</span> <span class="hljs-string">'./routes/personal/MyProfile'</span>)
</div><div class="hljs-line">        ),
</div><div class="hljs-line">        <span class="hljs-attr">meta</span>: { <span class="hljs-attr">title</span>: <span class="hljs-string">'个人中心-我的信息'</span> }
</div><div class="hljs-line">    }]
</div><div class="hljs-line">}, {
</div><div class="hljs-line">    <span class="hljs-attr">redirect</span>: <span class="hljs-literal">true</span>,
</div><div class="hljs-line">    <span class="hljs-attr">to</span>: <span class="hljs-string">'/'</span>
</div><div class="hljs-line">}];
</div><div class="hljs-line"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> routes;
</div></code></pre>

    <p>router.js</p>



    <pre class="prettyprint hljs-dark"><code class="language-javascript hljs"><div class="hljs-line"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
</div><div class="hljs-line"><span class="hljs-keyword">import</span> { Router, Route, Switch, Redirect } <span class="hljs-keyword">from</span> <span class="hljs-string">'dva/router'</span>;
</div><div class="hljs-line"><span class="hljs-keyword">import</span> routes <span class="hljs-keyword">from</span> <span class="hljs-string">'./routerRoutes'</span>;
</div><div class="hljs-line"><span class="hljs-comment">/* ANTD */</span>
</div><div class="hljs-line">...
</div><div class="hljs-line"><span class="hljs-comment">/* 动态创建路由 */</span>
</div><div class="hljs-line"><span class="hljs-keyword">const</span> createRoute = <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">createRoute</span>(<span class="hljs-params">routes</span>) </span>{
</div><div class="hljs-line">  <span class="hljs-keyword">return</span> &lt;Switch&gt;
</div><div class="hljs-line">    {routes.map((item, index) =&gt; {
</div><div class="hljs-line">      let { redirect, from, to, exact, path, meta, component: Component } = item,
</div><div class="hljs-line">        config = {};
</div><div class="hljs-line">      // 重定向
</div><div class="hljs-line">      if (redirect) {
</div><div class="hljs-line">        config = { to };
</div><div class="hljs-line">        if (from) config.from = from;
</div><div class="hljs-line">        if (exact) config.exact = exact;
</div><div class="hljs-line">        return &lt;Redirect {...config} key={index} /&gt;;
</div><div class="hljs-line">      }
</div><div class="hljs-line">      // 正常路由
</div><div class="hljs-line">      config = { path };
</div><div class="hljs-line">      if (exact) config.exact = exact;
</div><div class="hljs-line">      return &lt;Route {...config} key={index}
</div><div class="hljs-line">        render={(props) =&gt; {
</div><div class="hljs-line">          // 修改标题
</div><div class="hljs-line">          let { title = '' } = meta;
</div><div class="hljs-line">          document.title = `${title}-珠峰培训React`;
</div><div class="hljs-line">          return &lt;Component {...props} /&gt;;
</div><div class="hljs-line">        }} /&gt;;
</div><div class="hljs-line">    })}
</div><div class="hljs-line">  &lt;/Switch&gt;;
</div><div class="hljs-line">};
</div><div class="hljs-line">/* 一级路由 */
</div><div class="hljs-line">const RouterConfig = function RouterConfig({ history }) {
</div><div class="hljs-line">  return &lt;ConfigProvider locale={zhCN}&gt;
</div><div class="hljs-line">    &lt;Router history={history}&gt;
</div><div class="hljs-line">      {createRoute(routes)}
</div><div class="hljs-line">    &lt;/Router&gt;
</div><div class="hljs-line">  &lt;/ConfigProvider&gt;;
</div><div class="hljs-line">};
</div><div class="hljs-line">/* 二级路由 */
</div><div class="hljs-line">export const childrenRouter = function childrenRouter(path) {
</div><div class="hljs-line">  let item = routes.find(item =&gt; item.path === path),
</div><div class="hljs-line">    children;
</div><div class="hljs-line">  if (item) children = item.children;
</div><div class="hljs-line">  if (!children) return null;
</div><div class="hljs-line">  return createRoute(children);
</div><div class="hljs-line">};
</div><div class="hljs-line">export default RouterConfig;
</div></code></pre>

    <p>index.js</p>



    <pre class="prettyprint hljs-dark"><code class="language-javascript hljs"><div class="hljs-line"><span class="hljs-keyword">import</span> dva <span class="hljs-keyword">from</span> <span class="hljs-string">'dva'</span>;
</div><div class="hljs-line"><span class="hljs-keyword">import</span> createHistory <span class="hljs-keyword">from</span> <span class="hljs-string">'history/createHashHistory'</span>;
</div><div class="hljs-line"><span class="hljs-keyword">import</span> voteModel <span class="hljs-keyword">from</span> <span class="hljs-string">'./models/voteModel'</span>;
</div><div class="hljs-line"><span class="hljs-comment">// 1. Initialize</span>
</div><div class="hljs-line"><span class="hljs-keyword">const</span> app = dva({
</div><div class="hljs-line">    <span class="hljs-attr">history</span>: createHistory()
</div><div class="hljs-line">});
</div><div class="hljs-line"><span class="hljs-built_in">window</span>.app = app;
</div><div class="hljs-line"><span class="hljs-comment">// 2. Plugins</span>
</div><div class="hljs-line"><span class="hljs-comment">// app.use({});</span>
</div><div class="hljs-line"><span class="hljs-comment">// 3. Model</span>
</div><div class="hljs-line">app.model(voteModel);
</div><div class="hljs-line"><span class="hljs-comment">// 4. Router</span>
</div><div class="hljs-line">app.router(<span class="hljs-built_in">require</span>(<span class="hljs-string">'./router'</span>).default);
</div><div class="hljs-line"><span class="hljs-comment">// 5. Start</span>
</div><div class="hljs-line">app.start(<span class="hljs-string">'#root'</span>);
</div></code></pre>

    <p>Personal.jsx</p>



    <pre class="prettyprint hljs-dark"><code class="language-javascript hljs"><div class="hljs-line"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
</div><div class="hljs-line"><span class="hljs-keyword">import</span> { NavLink } <span class="hljs-keyword">from</span> <span class="hljs-string">'dva/router'</span>;
</div><div class="hljs-line"><span class="hljs-keyword">import</span> styled <span class="hljs-keyword">from</span> <span class="hljs-string">"styled-components"</span>;
</div><div class="hljs-line"><span class="hljs-keyword">import</span> { childrenRouter } <span class="hljs-keyword">from</span> <span class="hljs-string">'../router'</span>;
</div><div class="hljs-line"><span class="hljs-comment">/* 样式处理 */</span>
</div><div class="hljs-line"><span class="hljs-keyword">const</span> PersonalBox = styled.div<span class="hljs-string">`</span>
</div><div class="hljs-line"><span class="hljs-string">    ...</span>
</div><div class="hljs-line"><span class="hljs-string">`</span>;
</div><div class="hljs-line"><span class="hljs-keyword">const</span> Personal = <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Personal</span>(<span class="hljs-params"></span>) </span>{
</div><div class="hljs-line">    <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">PersonalBox</span>&gt;</span></span>
</div><div class="hljs-line"><span class="xml">        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"menu"</span>&gt;</span></span>
</div><div class="hljs-line"><span class="xml">            <span class="hljs-tag">&lt;<span class="hljs-name">NavLink</span> <span class="hljs-attr">to</span>=<span class="hljs-string">"/personal/order"</span>&gt;</span>我的订单<span class="hljs-tag">&lt;/<span class="hljs-name">NavLink</span>&gt;</span></span>
</div><div class="hljs-line"><span class="xml">            <span class="hljs-tag">&lt;<span class="hljs-name">NavLink</span> <span class="hljs-attr">to</span>=<span class="hljs-string">"/personal/profile"</span>&gt;</span>我的信息<span class="hljs-tag">&lt;/<span class="hljs-name">NavLink</span>&gt;</span></span>
</div><div class="hljs-line"><span class="xml">        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
</div><div class="hljs-line"><span class="xml">        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"content"</span>&gt;</span></span>
</div><div class="hljs-line"><span class="xml">            {childrenRouter('/personal')}</span>
</div><div class="hljs-line"><span class="xml">        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
</div><div class="hljs-line"><span class="xml">    <span class="hljs-tag">&lt;/<span class="hljs-name">PersonalBox</span>&gt;</span></span>;
</div><div class="hljs-line">};
</div><div class="hljs-line"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> Personal;
</div></code></pre>

    <p><code>路由跳转及传参</code> <br>
      方案一：Link 和 NavLink <br>
      NavLink可以和路由地址进行匹配，设置选中样式！！</p>



    <pre class="prettyprint hljs-dark"><code class="hljs xml"><div class="hljs-line"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"menu"</span>&gt;</span>
</div><div class="hljs-line">    <span class="hljs-tag">&lt;<span class="hljs-name">NavLink</span> <span class="hljs-attr">to</span>=<span class="hljs-string">"/personal/order"</span>&gt;</span>我的订单<span class="hljs-tag">&lt;/<span class="hljs-name">NavLink</span>&gt;</span>
</div><div class="hljs-line">    <span class="hljs-tag">&lt;<span class="hljs-name">NavLink</span> <span class="hljs-attr">to</span>=<span class="hljs-string">"/personal/profile"</span>&gt;</span>我的信息<span class="hljs-tag">&lt;/<span class="hljs-name">NavLink</span>&gt;</span>
</div><div class="hljs-line"><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
</div></code></pre>

    <p>方案二：编程式导航</p>



    <pre class="prettyprint hljs-dark"><code class="hljs javascript"><div class="hljs-line"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
</div><div class="hljs-line"><span class="hljs-keyword">import</span> { routerRedux } <span class="hljs-keyword">from</span> <span class="hljs-string">'dva/router'</span>;
</div><div class="hljs-line"><span class="hljs-keyword">import</span> { connect } <span class="hljs-keyword">from</span> <span class="hljs-string">'dva'</span>;
</div><div class="hljs-line"><wbr>
</div><div class="hljs-line"><span class="hljs-keyword">const</span> MyOrder = <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">MyOrder</span>(<span class="hljs-params">props</span>) </span>{
</div><div class="hljs-line">    <span class="hljs-comment">/* </span>
</div><div class="hljs-line"><span class="hljs-comment">    基于路由匹配的组件，其属性中包含：history、location、match！</span>
</div><div class="hljs-line"><span class="hljs-comment">      其中history就是实现路由跳转的</span>
</div><div class="hljs-line"><span class="hljs-comment">        + push</span>
</div><div class="hljs-line"><span class="hljs-comment">        + replace</span>
</div><div class="hljs-line"><span class="hljs-comment">        + go</span>
</div><div class="hljs-line"><span class="hljs-comment">        + goBack</span>
</div><div class="hljs-line"><span class="hljs-comment">        + goForward</span>
</div><div class="hljs-line"><span class="hljs-comment">      如果组件不是基于路由匹配的，可以基于 withRouter 高阶函数处理即可！！</span>
</div><div class="hljs-line"><span class="hljs-comment">    */</span>
</div><div class="hljs-line">    <span class="hljs-keyword">let</span> { history, dispatch } = props;
</div><div class="hljs-line">    <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"myOrderBox"</span>&gt;</span></span>
</div><div class="hljs-line"><span class="xml">        我的订单</span>
</div><div class="hljs-line"><span class="xml">        <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> {</span>
</div><div class="hljs-line"><span class="xml">            // history.push('/personal/profile');</span>
</div><div class="hljs-line"><span class="xml"></span>
</div><div class="hljs-line"><span class="xml">            /* </span>
</div><div class="hljs-line"><span class="xml">             routerRedux 也可以实现路由跳转，语法和history类似</span>
</div><div class="hljs-line"><span class="xml">             好处：可以在Effects中基于 yield 实现路由跳转</span>
</div><div class="hljs-line"><span class="xml">                // Inside Effects</span>
</div><div class="hljs-line"><span class="xml">                yield put(routerRedux.push('/logout'));</span>
</div><div class="hljs-line"><span class="xml"></span>
</div><div class="hljs-line"><span class="xml">                // Outside Effects</span>
</div><div class="hljs-line"><span class="xml">                dispatch(routerRedux.push('/logout'));</span>
</div><div class="hljs-line"><span class="xml">             */</span>
</div><div class="hljs-line"><span class="xml">            dispatch(routerRedux.push('/personal/profile'));</span>
</div><div class="hljs-line"><span class="xml">        }}&gt;跳转<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span></span>
</div><div class="hljs-line"><span class="xml">    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>;
</div><div class="hljs-line">};
</div><div class="hljs-line"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> connect()(MyOrder);
</div></code></pre>

    <hr>



    <h4 id="3-dva中model处理">3. dva中Model处理</h4>

    <p><code>入口</code></p>



    <pre class="prettyprint hljs-dark"><code class="language-javascript hljs"><div class="hljs-line"><span class="hljs-keyword">import</span> voteModel <span class="hljs-keyword">from</span> <span class="hljs-string">'./models/voteModel'</span>;
</div><div class="hljs-line">...
</div><div class="hljs-line">app.model(voteModel);
</div><div class="hljs-line">...
</div></code></pre>

    <p><code>基本结构</code></p>



    <pre class="prettyprint hljs-dark"><code class="language-javascript hljs"><div class="hljs-line"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> {
</div><div class="hljs-line">    <span class="hljs-comment">// 命名空间「模块名：后期获取状态和派发都需要这个名字」</span>
</div><div class="hljs-line">    namespace: <span class="hljs-string">'vote'</span>,
</div><div class="hljs-line">    <span class="hljs-comment">// 此模块管理的公共状态</span>
</div><div class="hljs-line">    state: {},
</div><div class="hljs-line">    <span class="hljs-comment">// 此模块需要判断的reducer「同步派发直达reducers」</span>
</div><div class="hljs-line">    reducers: {},
</div><div class="hljs-line">    <span class="hljs-comment">// 此模块需要异步派发的任务「基于redux-saga语法处理」</span>
</div><div class="hljs-line">    effects: {},
</div><div class="hljs-line">    <span class="hljs-comment">// 订阅方法，一开始就自动执行「获取数据，实现派发等」</span>
</div><div class="hljs-line">    subscriptions: {}
</div><div class="hljs-line">};
</div></code></pre>

    <p><code>实现计数器累计</code> <br>
      Demo.jsx</p>



    <pre class="prettyprint hljs-dark"><code class="hljs javascript"><div class="hljs-line"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
</div><div class="hljs-line"><span class="hljs-keyword">import</span> styled <span class="hljs-keyword">from</span> <span class="hljs-string">"styled-components"</span>;
</div><div class="hljs-line"><span class="hljs-keyword">import</span> { connect } <span class="hljs-keyword">from</span> <span class="hljs-string">'dva'</span>
</div><div class="hljs-line"><span class="hljs-keyword">import</span> { Button } <span class="hljs-keyword">from</span> <span class="hljs-string">'antd'</span>;
</div><div class="hljs-line">...
</div><div class="hljs-line">const Demo = <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Demo</span>(<span class="hljs-params">props</span>) </span>{
</div><div class="hljs-line">    <span class="hljs-keyword">let</span> { num, dispatch } = props;
</div><div class="hljs-line">    <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">DemoBox</span>&gt;</span></span>
</div><div class="hljs-line"><span class="xml">        <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"num"</span>&gt;</span>{num}<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span></span>
</div><div class="hljs-line"><span class="xml">        <span class="hljs-tag">&lt;<span class="hljs-name">Button</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"primary"</span></span></span>
</div><div class="hljs-line"><span class="xml">            <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt; {</span>
</div><div class="hljs-line"><span class="xml">                dispatch({</span>
</div><div class="hljs-line"><span class="xml">                    type: "demo/increment",</span>
</div><div class="hljs-line"><span class="xml">                    payload: 5</span>
</div><div class="hljs-line"><span class="xml">                });</span>
</div><div class="hljs-line"><span class="xml">            }}&gt;</span>
</div><div class="hljs-line"><span class="xml">            按钮</span>
</div><div class="hljs-line"><span class="xml">        <span class="hljs-tag">&lt;/<span class="hljs-name">Button</span>&gt;</span></span>
</div><div class="hljs-line"><span class="xml">        <span class="hljs-tag">&lt;<span class="hljs-name">Button</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"primary"</span> <span class="hljs-attr">danger</span></span></span>
</div><div class="hljs-line"><span class="xml">            <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt; {</span>
</div><div class="hljs-line"><span class="xml">                dispatch({</span>
</div><div class="hljs-line"><span class="xml">                    type: 'demo/incrementAsync',</span>
</div><div class="hljs-line"><span class="xml">                    payload: 10</span>
</div><div class="hljs-line"><span class="xml">                });</span>
</div><div class="hljs-line"><span class="xml">            }}&gt;</span>
</div><div class="hljs-line"><span class="xml">            异步按钮</span>
</div><div class="hljs-line"><span class="xml">        <span class="hljs-tag">&lt;/<span class="hljs-name">Button</span>&gt;</span></span>
</div><div class="hljs-line"><span class="xml">    <span class="hljs-tag">&lt;/<span class="hljs-name">DemoBox</span>&gt;</span></span>;
</div><div class="hljs-line">};
</div><div class="hljs-line"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> connect(<span class="hljs-function"><span class="hljs-params">state</span> =&gt;</span> state.demo)(Demo);
</div></code></pre>

    <p>demoModel.js</p>



    <pre class="prettyprint hljs-dark"><code class="language-javascript hljs"><div class="hljs-line"><span class="hljs-keyword">import</span> _ <span class="hljs-keyword">from</span> <span class="hljs-string">'../utils/utils'</span>;
</div><div class="hljs-line"><span class="hljs-keyword">const</span> delay = <span class="hljs-function">(<span class="hljs-params">interval = <span class="hljs-number">1000</span></span>) =&gt;</span> {
</div><div class="hljs-line">    ...
</div><div class="hljs-line">};
</div><div class="hljs-line"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> {
</div><div class="hljs-line">    <span class="hljs-attr">namespace</span>: <span class="hljs-string">'demo'</span>,
</div><div class="hljs-line">    <span class="hljs-attr">state</span>: {
</div><div class="hljs-line">        <span class="hljs-attr">num</span>: <span class="hljs-number">0</span>
</div><div class="hljs-line">    },
</div><div class="hljs-line">    <span class="hljs-attr">reducers</span>: {
</div><div class="hljs-line">        increment(state, action) {
</div><div class="hljs-line">            state = _.clone(<span class="hljs-literal">true</span>, state);
</div><div class="hljs-line">            <span class="hljs-keyword">let</span> { payload = <span class="hljs-number">1</span> } = action;
</div><div class="hljs-line">            state.num += payload;
</div><div class="hljs-line">            <span class="hljs-keyword">return</span> state;
</div><div class="hljs-line">        }
</div><div class="hljs-line">    },
</div><div class="hljs-line">    <span class="hljs-attr">effects</span>: {
</div><div class="hljs-line">        *incrementAsync({ payload }, { call, put }) {
</div><div class="hljs-line">            <span class="hljs-keyword">yield</span> call(delay, <span class="hljs-number">2000</span>);
</div><div class="hljs-line">            <span class="hljs-keyword">yield</span> put({
</div><div class="hljs-line">                <span class="hljs-attr">type</span>: <span class="hljs-string">'increment'</span>,
</div><div class="hljs-line">                payload
</div><div class="hljs-line">            });
</div><div class="hljs-line">        }
</div><div class="hljs-line">    }
</div><div class="hljs-line">};
</div></code></pre>

    <p><code>effects中的特殊处理</code></p>



    <pre class="prettyprint hljs-dark"><code class="language-javascript hljs"><div class="hljs-line">effects: {
</div><div class="hljs-line">    <span class="hljs-attr">incrementAsync</span>: [
</div><div class="hljs-line">        <span class="hljs-function"><span class="hljs-keyword">function</span>* (<span class="hljs-params">{ payload }, { call, put, select }</span>) </span>{
</div><div class="hljs-line">            <span class="hljs-keyword">try</span> {
</div><div class="hljs-line">                <span class="hljs-comment">// 获取状态</span>
</div><div class="hljs-line">                <span class="hljs-keyword">let</span> { num } = <span class="hljs-keyword">yield</span> select(<span class="hljs-function"><span class="hljs-params">state</span> =&gt;</span> state.demo);
</div><div class="hljs-line">                <span class="hljs-comment">// 发送请求</span>
</div><div class="hljs-line">                <span class="hljs-keyword">yield</span> call(delay, <span class="hljs-number">2000</span>);
</div><div class="hljs-line">                <span class="hljs-comment">// 派发任务</span>
</div><div class="hljs-line">                <span class="hljs-keyword">yield</span> put({
</div><div class="hljs-line">                    <span class="hljs-attr">type</span>: <span class="hljs-string">'increment'</span>,
</div><div class="hljs-line">                    payload
</div><div class="hljs-line">                });
</div><div class="hljs-line">            } <span class="hljs-keyword">catch</span> (err) {
</div><div class="hljs-line">                <span class="hljs-comment">// 异常捕获</span>
</div><div class="hljs-line">                <span class="hljs-built_in">console</span>.log(err);
</div><div class="hljs-line">            }
</div><div class="hljs-line">        },
</div><div class="hljs-line">        <span class="hljs-comment">// 指定监听的类型，默认是takeEvery「还有：takeLatest、throttle等」</span>
</div><div class="hljs-line">        { <span class="hljs-attr">type</span>: <span class="hljs-string">"takeLatest"</span> },
</div><div class="hljs-line">        <span class="hljs-comment">// { type: "throttle", ms: 1000 }</span>
</div><div class="hljs-line">    ]
</div><div class="hljs-line">}
</div></code></pre>

    <p><code>subscriptions</code></p>



    <pre class="prettyprint hljs-dark"><code class="language-javascript hljs"><div class="hljs-line">app.model({
</div><div class="hljs-line">    <span class="hljs-attr">subscriptions</span>: {
</div><div class="hljs-line">        setup({ dispatch, history }) {
</div><div class="hljs-line">            history.listen(<span class="hljs-function"><span class="hljs-params">location</span> =&gt;</span> {
</div><div class="hljs-line">                <span class="hljs-keyword">if</span> (location.pathname === <span class="hljs-string">'/demo'</span>) {
</div><div class="hljs-line">                    dispatch({
</div><div class="hljs-line">                        <span class="hljs-attr">type</span>: <span class="hljs-string">'demo/increment'</span>,
</div><div class="hljs-line">                        <span class="hljs-attr">payload</span>: <span class="hljs-number">100</span>
</div><div class="hljs-line">                    });
</div><div class="hljs-line">                }
</div><div class="hljs-line">            });
</div><div class="hljs-line">        }
</div><div class="hljs-line">    }
</div><div class="hljs-line">})
</div></code></pre>

    <hr>



    <h4 id="4-dva-loading插件的应用">4. dva-loading插件的应用</h4>

    <blockquote>
      <p>dva-loading 会监听指定的异步请求方法，方法开始时loading状态值为 true ，异步结束后该值自动置为 false , 可用于骨架屏或某些需要 loading 状态的场景！ <br>
        $ yarn add dva-loading</p>
    </blockquote>

    <p>index.js</p>

    <pre class="prettyprint hljs-dark"><code class="language-javascript hljs"><div class="hljs-line"><span class="hljs-keyword">import</span> createLoading <span class="hljs-keyword">from</span> <span class="hljs-string">'dva-loading'</span>;
</div><div class="hljs-line">...
</div><div class="hljs-line">app.use(createLoading());
</div><div class="hljs-line">...
</div></code></pre>

    <p>models/demoModel.js</p>



    <pre class="prettyprint hljs-dark"><code class="language-javascript hljs"><div class="hljs-line"><span class="hljs-keyword">const</span> delay = <span class="hljs-function">(<span class="hljs-params">interval = <span class="hljs-number">1000</span></span>) =&gt;</span> {
</div><div class="hljs-line">    ...
</div><div class="hljs-line">};
</div><div class="hljs-line"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> {
</div><div class="hljs-line">    <span class="hljs-attr">namespace</span>: <span class="hljs-string">'demo'</span>,
</div><div class="hljs-line">    <span class="hljs-attr">state</span>: {
</div><div class="hljs-line">        <span class="hljs-attr">num</span>: <span class="hljs-number">0</span>
</div><div class="hljs-line">    },
</div><div class="hljs-line">    <span class="hljs-attr">reducers</span>: {
</div><div class="hljs-line">        test(state) {
</div><div class="hljs-line">            state = { ...state };
</div><div class="hljs-line">            state.num++;
</div><div class="hljs-line">            <span class="hljs-keyword">return</span> state;
</div><div class="hljs-line">        }
</div><div class="hljs-line">    },
</div><div class="hljs-line">    <span class="hljs-attr">effects</span>: {
</div><div class="hljs-line">        *testAsync(action, { call, put }) {
</div><div class="hljs-line">            <span class="hljs-keyword">yield</span> call(delay, <span class="hljs-number">2000</span>);
</div><div class="hljs-line">            <span class="hljs-keyword">yield</span> put({
</div><div class="hljs-line">                <span class="hljs-attr">type</span>: <span class="hljs-string">'test'</span>
</div><div class="hljs-line">            });
</div><div class="hljs-line">        }
</div><div class="hljs-line">    }
</div><div class="hljs-line">};
</div></code></pre>

    <p>组件中使用</p>



    <pre class="prettyprint hljs-dark"><code class="language-javascript hljs"><div class="hljs-line"><span class="hljs-keyword">import</span> { connect } <span class="hljs-keyword">from</span> <span class="hljs-string">"dva"</span>;
</div><div class="hljs-line">...
</div><div class="hljs-line">const Demo = <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Demo</span>(<span class="hljs-params">{ num, loading, dispatch }</span>) </span>{
</div><div class="hljs-line">    loading = loading.effects[<span class="hljs-string">'demo/testAsync'</span>];
</div><div class="hljs-line">    <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">DemoBox</span>&gt;</span></span>
</div><div class="hljs-line"><span class="xml">        <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"num"</span>&gt;</span>{num}<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span></span>
</div><div class="hljs-line"><span class="xml">        <span class="hljs-tag">&lt;<span class="hljs-name">Button</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"primary"</span> <span class="hljs-attr">danger</span></span></span>
</div><div class="hljs-line"><span class="xml">            <span class="hljs-attr">loading</span>=<span class="hljs-string">{loading}</span></span>
</div><div class="hljs-line"><span class="xml">            <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt; {</span>
</div><div class="hljs-line"><span class="xml">                dispatch({ type: 'demo/testAsync' });</span>
</div><div class="hljs-line"><span class="xml">            }}&gt;</span>
</div><div class="hljs-line"><span class="xml">            异步按钮</span>
</div><div class="hljs-line"><span class="xml">        <span class="hljs-tag">&lt;/<span class="hljs-name">Button</span>&gt;</span></span>
</div><div class="hljs-line"><span class="xml">    <span class="hljs-tag">&lt;/<span class="hljs-name">DemoBox</span>&gt;</span></span>;
</div><div class="hljs-line">};
</div><div class="hljs-line"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> connect(
</div><div class="hljs-line">    <span class="hljs-function"><span class="hljs-params">state</span> =&gt;</span> {
</div><div class="hljs-line">        <span class="hljs-keyword">return</span> {
</div><div class="hljs-line">            ...state.demo,
</div><div class="hljs-line">            <span class="hljs-attr">loading</span>: state.loading
</div><div class="hljs-line">        };
</div><div class="hljs-line">    }
</div><div class="hljs-line">)(Demo);
</div></code></pre>

    <hr>

    <h4 id="5-基于dva重写投票案例">5. 基于dva重写投票案例</h4>

    <p>voteModel.js</p>



    <pre class="prettyprint hljs-dark"><code class="language-javascript hljs"><div class="hljs-line"><span class="hljs-keyword">import</span> _ <span class="hljs-keyword">from</span> <span class="hljs-string">'../utils/utils'</span>;
</div><div class="hljs-line"><span class="hljs-keyword">const</span> delay = <span class="hljs-function">(<span class="hljs-params">interval = <span class="hljs-number">1000</span></span>) =&gt;</span> {
</div><div class="hljs-line">    <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function"><span class="hljs-params">resolve</span> =&gt;</span> {
</div><div class="hljs-line">        setTimeout(<span class="hljs-function"><span class="hljs-params">()</span> =&gt;</span> {
</div><div class="hljs-line">            resolve();
</div><div class="hljs-line">        }, interval);
</div><div class="hljs-line">    });
</div><div class="hljs-line">};
</div><div class="hljs-line"><wbr>
</div><div class="hljs-line"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> {
</div><div class="hljs-line">    <span class="hljs-attr">namespace</span>: <span class="hljs-string">'vote'</span>,
</div><div class="hljs-line">    <span class="hljs-attr">state</span>: {
</div><div class="hljs-line">        <span class="hljs-attr">supNum</span>: <span class="hljs-number">10</span>,
</div><div class="hljs-line">        <span class="hljs-attr">oppNum</span>: <span class="hljs-number">5</span>
</div><div class="hljs-line">    },
</div><div class="hljs-line">    <span class="hljs-attr">reducers</span>: {
</div><div class="hljs-line">        support(state, action) {
</div><div class="hljs-line">            state = _.clone(<span class="hljs-literal">true</span>, state);
</div><div class="hljs-line">            <span class="hljs-keyword">let</span> { payload = <span class="hljs-number">1</span> } = action;
</div><div class="hljs-line">            state.supNum += payload;
</div><div class="hljs-line">            <span class="hljs-keyword">return</span> state;
</div><div class="hljs-line">        },
</div><div class="hljs-line">        oppose(state, action) {
</div><div class="hljs-line">            state = _.clone(<span class="hljs-literal">true</span>, state);
</div><div class="hljs-line">            <span class="hljs-keyword">let</span> { payload = <span class="hljs-number">1</span> } = action;
</div><div class="hljs-line">            state.oppNum += payload;
</div><div class="hljs-line">            <span class="hljs-keyword">return</span> state;
</div><div class="hljs-line">        }
</div><div class="hljs-line">    },
</div><div class="hljs-line">    <span class="hljs-attr">effects</span>: {
</div><div class="hljs-line">        <span class="hljs-attr">supportAsync</span>: [
</div><div class="hljs-line">            <span class="hljs-function"><span class="hljs-keyword">function</span>* (<span class="hljs-params">{ payload }, { call, put }</span>) </span>{
</div><div class="hljs-line">                <span class="hljs-keyword">yield</span> call(delay, <span class="hljs-number">2000</span>);
</div><div class="hljs-line">                <span class="hljs-keyword">yield</span> put({
</div><div class="hljs-line">                    <span class="hljs-attr">type</span>: <span class="hljs-string">'support'</span>,
</div><div class="hljs-line">                    payload
</div><div class="hljs-line">                });
</div><div class="hljs-line">            },
</div><div class="hljs-line">            { <span class="hljs-attr">type</span>: <span class="hljs-string">'takeLatest'</span> }
</div><div class="hljs-line">        ],
</div><div class="hljs-line">        <span class="hljs-attr">opposeAsync</span>: [
</div><div class="hljs-line">            <span class="hljs-function"><span class="hljs-keyword">function</span>* <span class="hljs-title">opposeAsync</span>(<span class="hljs-params">{ payload }, { call, put }</span>) </span>{
</div><div class="hljs-line">                <span class="hljs-keyword">yield</span> call(delay, <span class="hljs-number">2000</span>);
</div><div class="hljs-line">                <span class="hljs-keyword">yield</span> put({
</div><div class="hljs-line">                    <span class="hljs-attr">type</span>: <span class="hljs-string">'oppose'</span>,
</div><div class="hljs-line">                    payload
</div><div class="hljs-line">                });
</div><div class="hljs-line">            },
</div><div class="hljs-line">            { <span class="hljs-attr">type</span>: <span class="hljs-string">'takeLatest'</span> }
</div><div class="hljs-line">        ]
</div><div class="hljs-line">    }
</div><div class="hljs-line">};
</div></code></pre>

    <p>Vote.jsx</p>



    <pre class="prettyprint hljs-dark"><code class="hljs javascript"><div class="hljs-line"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
</div><div class="hljs-line"><span class="hljs-keyword">import</span> styled <span class="hljs-keyword">from</span> <span class="hljs-string">"styled-components"</span>;
</div><div class="hljs-line"><span class="hljs-keyword">import</span> { Button } <span class="hljs-keyword">from</span> <span class="hljs-string">'antd'</span>;
</div><div class="hljs-line"><span class="hljs-keyword">import</span> { connect } <span class="hljs-keyword">from</span> <span class="hljs-string">'dva'</span>;
</div><div class="hljs-line">...
</div><div class="hljs-line">const Vote = <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Vote</span>(<span class="hljs-params">props</span>) </span>{
</div><div class="hljs-line">    <span class="hljs-keyword">let</span> { supNum, oppNum, dispatch } = props;
</div><div class="hljs-line">    <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">VoteBox</span>&gt;</span></span>
</div><div class="hljs-line"><span class="xml">        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"header"</span>&gt;</span></span>
</div><div class="hljs-line"><span class="xml">            <span class="hljs-tag">&lt;<span class="hljs-name">h2</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"title"</span>&gt;</span>React是很棒的前端框架<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span></span>
</div><div class="hljs-line"><span class="xml">            <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"num"</span>&gt;</span>{supNum + oppNum}<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span></span>
</div><div class="hljs-line"><span class="xml">        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
</div><div class="hljs-line"><span class="xml">        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"main"</span>&gt;</span></span>
</div><div class="hljs-line"><span class="xml">            <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>支持人数：{supNum}人<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></span>
</div><div class="hljs-line"><span class="xml">            <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>反对人数：{oppNum}人<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></span>
</div><div class="hljs-line"><span class="xml">        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
</div><div class="hljs-line"><span class="xml">        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"footer"</span>&gt;</span></span>
</div><div class="hljs-line"><span class="xml">            <span class="hljs-tag">&lt;<span class="hljs-name">Button</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"primary"</span></span></span>
</div><div class="hljs-line"><span class="xml">                <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt; {</span>
</div><div class="hljs-line"><span class="xml">                    dispatch({</span>
</div><div class="hljs-line"><span class="xml">                        type: 'vote/supportAsync',</span>
</div><div class="hljs-line"><span class="xml">                        payload: 10</span>
</div><div class="hljs-line"><span class="xml">                    });</span>
</div><div class="hljs-line"><span class="xml">                }}&gt;</span>
</div><div class="hljs-line"><span class="xml">                支持</span>
</div><div class="hljs-line"><span class="xml">            <span class="hljs-tag">&lt;/<span class="hljs-name">Button</span>&gt;</span></span>
</div><div class="hljs-line"><span class="xml">            <span class="hljs-tag">&lt;<span class="hljs-name">Button</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"primary"</span> <span class="hljs-attr">danger</span></span></span>
</div><div class="hljs-line"><span class="xml">                <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt; {</span>
</div><div class="hljs-line"><span class="xml">                    dispatch({</span>
</div><div class="hljs-line"><span class="xml">                        type: 'vote/opposeAsync'</span>
</div><div class="hljs-line"><span class="xml">                    });</span>
</div><div class="hljs-line"><span class="xml">                }}&gt;</span>
</div><div class="hljs-line"><span class="xml">                反对</span>
</div><div class="hljs-line"><span class="xml">            <span class="hljs-tag">&lt;/<span class="hljs-name">Button</span>&gt;</span></span>
</div><div class="hljs-line"><span class="xml">        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
</div><div class="hljs-line"><span class="xml">    <span class="hljs-tag">&lt;/<span class="hljs-name">VoteBox</span>&gt;</span></span>;
</div><div class="hljs-line">};
</div><div class="hljs-line"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> connect(<span class="hljs-function"><span class="hljs-params">state</span> =&gt;</span> state.vote)(Vote);
</div></code></pre>
  </div>
</body>

</html>